//		Written by Todd Thomas Copyright (c) 1994 by Todd Thomas.
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import <misckit/MiscFile.h>
#import <misckit/MiscStopwatch.h>
#import <misckit/MiscSwapView.h>
#import "MainWinController.h"


@implementation MainWinController

// Create the object that will do the searching, and set us as the delegate,
// which will be used for multiple file searches.

- init
{
	[super init];
	infoPanel = nil;
	return self;
}



- free
{
//	[fileSearch free];
	return [super free];
}



// Executed when the "Begin Search" button was clicked. Make sure that all 
// fields that have to have values are fine, then do the search.

- beginSearch:sender
{
  BOOL  recursive, followLinks;
  id  pathname = nil;
  id  stopWatch = nil;
  id  fileSearch;
  int  i;
  
  	if (strcmp ([dirToSearch stringValue], "") == 0)
	{
		NXRunAlertPanel ("Insufficient Data", "You have not selected a directory to search.", "OK", 0, 0);
		return self;
	 }

	// get the search options
	recursive = [ [optionsMatrix cellAt: 0 : 0] state];
	followLinks = [ [optionsMatrix cellAt: 1 : 0] state];

	fileSearch = [ [MiscFile alloc] initWithPath: [dirToSearch stringValue] ];
	if (fileSearch == nil)
	{
		NXRunAlertPanel ("No way!", "Directory does not exist.", "OK", 0, 0);
		return self;
	 }
			
	// which search is done depends upon which cell is selected in
	// the popupList
	
	switch ([ [ [popup itemList] selectedCell] tag])
	{
	  case 1:			// do a single filename search
	  	
		// make sure that you have been given a filename to search for
		
		if (strcmp ([fileToSearchFor stringValue], "") == 0)
		{
			NXRunAlertPanel ("Insufficient Data", "You have not selected a filename to search for.", "OK", 0, 0);
			return self;
	 	 }
			
		[updator setStringValue: "Searching..."];
		[timerField setStringValue: ""];
		stopWatch = [ [ [MiscStopwatch alloc] init] startTiming: self];
		
		// do the search (MiscString returned if success, else nil)
		
		pathname = [fileSearch searchFor: [fileToSearchFor stringValue] 
				recursive: recursive followLinks: followLinks];

		// update the UI 		
		[stopWatch pauseTiming: self];
		[timerField setFloatValue: (float)[stopWatch minute]*60.0 + 
				(float)[stopWatch second] + 
				(float)[stopWatch microsecond]*1.0e-6];

		[stopWatch free];
		[self writeResults: pathname];
		
		if (pathname)
		{
			[updator setStringValue: ""];
			if (pathname != fileSearch)
				[pathname free];
		 }
		else
			[updator setStringValue: "Filename was not found."];
	
		break;

	  // do a multiple filename search (by extension)
	  
	  case 2:			
	  
	  	// make sure that the user gave an extension for the search
		
		if (strcmp ([extensionTextfield stringValue], "") == 0)
		{
			NXRunAlertPanel ("Insufficient Data", "You have not entered an extension to search for.", "OK", 0, 0);
			return self;
	 	 }
	  
	  	[updator setStringValue: "Searching..."];
		[timerField setStringValue: ""];
		stopWatch = [ [ [MiscStopwatch alloc] init] startTiming: self];
		
		// do the actual search (List of MiscStrings returned, or nil)
		
	  	pathname = [fileSearch searchFilesAndRecurse: recursive 
						followLinks: followLinks];

		// update the UI
		
		[stopWatch pauseTiming: self];
		[timerField setFloatValue: (float)[stopWatch minute]*60.0 + 
				(float)[stopWatch second] + 
				(float)[stopWatch microsecond]*1.0e-6];
		[stopWatch free];

		[self writeResults: pathname];				
		if (pathname)
		{
			[updator setStringValue: ""];
			for (i=0; i<[pathname count]; i++)
				if ([pathname objectAt: i] != fileSearch)
					[ [pathname removeObjectAt: i] free];
		 }
		else
			[updator setStringValue: "No matches were found."];
	  break;
		
	  default:
	  	NXRunAlertPanel ("Oops.", "Did you alter the popupList??.", "OK",
				0, 0);
	 }
	
	[fileSearch free];		
    return self;
}



// Set the directory to search via the OpenPanel.

- setDirectoryToSearch:sender
{
  id  openPanel = [OpenPanel new];
  
  	[openPanel chooseDirectories: YES];
	[openPanel setDirectory: NXHomeDirectory()];
	
	if ([openPanel runModal] == NX_OKTAG)
		[dirToSearch setStringValue: [openPanel filename] ];
		
	return self;
}



// Tries to write the result to the text contained within the scrollview.
// It will write the contents of either a single or list of MiscStrings.

- writeResults: result
{
  id  text = [scrollView docView];
  
  	[text setText: ""];
	
	if (result == nil)
		return self;
		
	if ([result class] == [List class])
	{
	  int  i, length;
	  
	  	for (i=0; i<[result count]; i++)
		{
			length = [text textLength];
			[text setSel: length : length];
			if (length > 0)
				[text replaceSel: "\n"];	
			[text replaceSel: [ [result objectAt: i] fullPath] ];
		 }
	 }
	
	if ([result respondsTo: @selector(stringValue)])
		[text setText: [result stringValue] ];
	if ([result respondsTo: @selector(fullPath)])
		[text setText: [result fullPath] ];

	return self;
}



- showInfoPanel: sender
{
    if (!infoPanel)
		infoPanel = [NXApp loadNibSection: "info.nib" owner: self];
		
	[infoPanel makeKeyAndOrderFront: self];

	return self;
}

@end



@implementation MainWinController (Initialization)

// Sets the updator textfield to nothing. (It gets set to "Searching..." when
// a search is taking place. Also ask the swapView to set itself to the 
// initial view.

- awakeFromNib
{
	[updator setStringValue: ""];
	[swapView setUseBuffering: YES];
	[swapView swapContentView: self];

	// Change the popup outlet from the cover to the actual popupList
	popup = [popup target];

	[ [MiscFile class] setClassDelegate: self];
	return self;
}

@end



@implementation MainWinController (MiscFileSearchingDelegate)

// This is the only method that a FileSearch delegate implements. Every
// filename in the search directory is sent here. For this example, we just 
// check the extension of the filename. If it matches what was entered 
// in the UI return YES (which adds it to the list of filenames returned).

- (BOOL)addFile: (MiscFile *)theFile 
{
  	char  *givenExtension = (char *)[extensionTextfield stringValue];
 
	if (givenExtension == NULL || [theFile extension] == NULL)
		return NO;
		
	if (strcmp (givenExtension, [theFile extension]) == 0)
		return YES;

	return NO;
}

@end

